
namespace smoothdev.K2.Blackpearl.ClientTools.Wrappers {
	using System;
	using System.Collections;
	using System.Collections.Generic;
	using System.Linq;
	
	/// <summary>
	/// Provides abstraction layer to other wrapper implementations
	/// </summary>
	/// <typeparam name="T"></typeparam>
	internal abstract class BaseDictionaryWrapper<T> : IDictionary {
		protected T wrappedInstance;

		protected internal BaseDictionaryWrapper(T wrappedInstance) {
			if(wrappedInstance == null) throw new ArgumentNullException("wrappedInstance");
			this.wrappedInstance = wrappedInstance;
		}

		protected internal abstract Func<IEnumerable<string>> keysIterator { get; }
		protected internal abstract Func<IEnumerable<object>> valuesIterator { get; }
		protected internal abstract Func<string, object> valueForKey { get; }
		protected internal abstract Action<string, object> valueForKeySetter { get; }
		protected internal abstract Func<int, object> valueAtIndexGetter { get; }
		protected internal abstract Action<int, object> valueAtIndexSetter { get; }
		protected internal abstract Func<int, string> keyAtIndex { get; }
		protected internal abstract Func<int> getCount { get; }

		public ICollection Keys { get { return new List<string>(keysIterator()); } }
		public ICollection Values { get { return new List<object>(valuesIterator()); } }
		IEnumerator IEnumerable.GetEnumerator() {
			var lazyResult =
				from
					k in keysIterator()
				select
					new KeyValuePair<string, object>(k, valueForKey(k));
			foreach (var pair in lazyResult)
				yield return pair;
		}

		public void CopyTo(Array array, int index) {
			var itemcount = getCount();
			if (index >= itemcount) throw new ArgumentOutOfRangeException("index");
			for (var i = index; i < itemcount; ++i)
				array.SetValue(new KeyValuePair<string, object>(keyAtIndex(i), valueAtIndexGetter(i)), i);
		}

		public int Count {
			get { return getCount(); }
		}

		public bool IsSynchronized {
			get { return false; }
		}

		public bool IsReadOnly {
			get { return false; }
		}

		public bool IsFixedSize {
			get { return true; }
		}

		public object this[object key] {
			get {
				var keyAsString = key as string;
				Guard.AgainstArgumentNotNull(keyAsString, "key");
				return valueForKey(keyAsString);
			}
			set {
				var keyAsString = key as string;
				Guard.AgainstArgumentNotNull(keyAsString, "key");
				valueForKeySetter(keyAsString, value);
			}
		}

		// theses members are not used nor implemented
		public void Remove(object key) {
			throw new NotImplementedException();
		}

		public bool Contains(object key) {
			throw new NotImplementedException();
		}

		public void Add(object key, object value) {
			throw new NotImplementedException();
		}

		public void Clear() {
			throw new NotImplementedException();
		}

		public IDictionaryEnumerator GetEnumerator() {
			throw new NotImplementedException();
		}

		public object SyncRoot {
			get { throw new NotImplementedException(); }
		}

	}
}